home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr05 / xnot12a.zip / KEYMAP.C < prev    next >
C/C++ Source or Header  |  1993-06-11  |  21KB  |  885 lines

  1. #include "jam.h"
  2. /*
  3.  * Keyboard maps.  This is character set dependent.
  4.  * The terminal specific parts of building the
  5.  * keymap has been moved to a better place.
  6.  */
  7. #include    "def.h"
  8. #include    "kbd.h"
  9.  
  10. #define KEYMAP_C
  11. #include "keyname.h"
  12.  
  13. /* hack for empty command
  14. */
  15. int donothing(f,n)
  16. int f,n;
  17. {
  18.   return (TRUE);
  19. }
  20.  
  21. static int rn_(name_fent,(char *fname, int flag));
  22.  
  23. /* initial keymap declarations, deepest first */
  24.  
  25. static    PF     cHcG[] = {
  26.     ctrlg,        /* ^G */
  27.     help_help,    /* ^H */
  28. };
  29. static    PF     cHa[]    = {
  30.     apropos_command,/* a */
  31.     wallchart,    /* b */
  32.     desckey,    /* c */
  33. };
  34. static    struct    KEYMAPE(2+IMAPEXT)    helpmap = {
  35.     2,
  36.     2+IMAPEXT,
  37.     rescan,
  38.     {
  39.         {CCHR('G'),CCHR('H'),    cHcG,(KEYMAP *)NULL},
  40.         {'a',    'c',        cHa,    (KEYMAP *)NULL},
  41.     }
  42. };
  43.  
  44. static    PF     cX4cF[] = {
  45.     poptofile,    /* ^f */
  46.     ctrlg,        /* ^g */
  47. };
  48. static    PF     cX4b[] = {
  49.     poptobuffer,    /* b */
  50.     rescan,        /* c */
  51.     rescan,        /* d */
  52.     rescan,        /* e */
  53.     poptofile,    /* f */
  54. };
  55. static    struct    KEYMAPE(2+IMAPEXT)    cX4map    = {
  56.     2,
  57.     2+IMAPEXT,
  58.     rescan,
  59.     {
  60.         {CCHR('F'),CCHR('G'),    cX4cF,    (KEYMAP *)NULL},
  61.         {'b',    'f',        cX4b,    (KEYMAP *)NULL},
  62.     }
  63. };
  64.  
  65. static    PF     cXcB[] = {
  66.     listbuffers,    /* ^B */
  67.     quit,        /* ^C */
  68.     rescan,        /* ^D */
  69.     rescan,        /* ^E */
  70.     filevisit,    /* ^F */
  71.     ctrlg,        /* ^G */
  72. };
  73. static    PF     cXcL[] = {
  74.     lowerregion,    /* ^L */
  75.     rescan,        /* ^M */
  76.     rescan,        /* ^N */
  77.     deblank,    /* ^O */
  78.     rescan,        /* ^P */
  79.     rescan,        /* ^Q */
  80.     rescan,        /* ^R */
  81.     filesave,    /* ^S */
  82.     rescan,        /* ^T */
  83.     upperregion,    /* ^U */
  84.     rescan,        /* ^V */
  85.     filewrite,    /* ^W */
  86.     swapmark,    /* ^X */
  87. };
  88.  
  89. static    PF     cXlp[]    = {
  90.     definemacro,    /* ( */
  91.     finishmacro,    /* ) */
  92. };
  93.  
  94. static    PF     cX0[]    = {
  95.     delwind,    /* 0 */
  96.     onlywind,    /* 1 */
  97.     splitwind,    /* 2 */
  98.     rescan,        /* 3 */
  99.     prefix,        /* 4 */
  100. };
  101. static    PF     cXeq[]    = {
  102.     showcpos,    /* = */
  103. };
  104. static    PF     cXcar[] = {
  105.     enlargewind,    /* ^ */
  106.     rescan,        /* _ */
  107.     rescan,        /* ` */
  108.     rescan,        /* a */
  109.     usebuffer,    /* b */
  110.     rescan,        /* c */
  111.     dired,        /* d */
  112.     executemacro,    /* e */
  113.     setfillcol,    /* f */
  114.     rescan,        /* g */
  115.     rescan,        /* h */
  116.     fileinsert,    /* i */
  117.     rescan,        /* j */
  118.     killbuffer,    /* k */
  119.     rescan,        /* l */
  120.     rescan,        /* m */
  121.     rescan,        /* n */
  122.     nextwind,    /* o */
  123.     rescan,        /* p */
  124.     rescan,        /* q */
  125.     rescan,        /* r */
  126.     savebuffers,    /* s */
  127. };
  128.  
  129. static    struct    KEYMAPE(6+IMAPEXT)    cXmap = {
  130.     6,
  131.     6+IMAPEXT,
  132.     rescan,
  133.     {
  134.         {CCHR('B'),CCHR('G'),    cXcB,    (KEYMAP *)NULL},
  135.         {CCHR('L'),CCHR('X'),    cXcL,    (KEYMAP *)NULL},
  136.         {'(',    ')',        cXlp,    (KEYMAP *)NULL},
  137.         {'0',    '4',        cX0,    (KEYMAP *)&cX4map},
  138.         {'=',    '=',        cXeq,    (KEYMAP *)NULL},
  139.         {'^',    's',        cXcar,    (KEYMAP *)NULL},
  140.     }
  141. };
  142.  
  143. static    PF     metacG[] = {
  144.     ctrlg,        /* ^G */
  145. };
  146. static    PF     metacV[] = {
  147.     pagenext,    /* ^V */
  148. };
  149. static    PF     metasp[] = {
  150.     justone,    /* space */
  151. };
  152. static    PF     metapct[] = {
  153.     queryrepl,    /* % */
  154. };
  155. static    PF     metami[] = {
  156.     negative_argument,    /* - */
  157.     rescan,        /* . */
  158.     rescan,        /* / */
  159.     digit_argument, /* 0 */
  160.     digit_argument, /* 1 */
  161.     digit_argument, /* 2 */
  162.     digit_argument, /* 3 */
  163.     digit_argument, /* 4 */
  164.     digit_argument, /* 5 */
  165.     digit_argument, /* 6 */
  166.     digit_argument, /* 7 */
  167.     digit_argument, /* 8 */
  168.     digit_argument, /* 9 */
  169.     rescan,        /* : */
  170.     rescan,        /* ; */
  171.     gotobob,    /* < */
  172.     rescan,        /* = */
  173.     gotoeob,    /* > */
  174. };
  175. static    PF     metalb[] = {
  176.     gotobop,    /* [ */
  177.     delwhite,    /* \ */
  178.     gotoeop,    /* ] */
  179.     rescan,      /* ^ */
  180.     rescan,         /*  */
  181.     rescan,       /* - */
  182.     rescan,        /* a */
  183.     backword,    /* b */
  184.     capword,    /* c */
  185.     delfword,    /* d */
  186.     rescan,        /* e */
  187.     forwword,    /* f */
  188. };
  189. static    PF     metal[] = {
  190.     lowerword,    /* l */
  191.     rescan,        /* m */
  192.     rescan,        /* n */
  193.     rescan,        /* o */
  194.     rescan,        /* p */
  195.     fillpara,    /* q */
  196.     backsearch,    /* r */
  197.     forwsearch,    /* s */
  198.     rescan,        /* t */
  199.     upperword,    /* u */
  200.     backpage,    /* v */
  201.     copyregion,    /* w */
  202.     extend,        /* x */
  203. };
  204. static    PF     metatilde[] = {
  205.     togglemodified,    /* ~ */
  206.     delbword,    /* DEL */
  207. };
  208. static    struct    KEYMAPE(8+IMAPEXT)    metamap = {
  209.     8,
  210.     8+IMAPEXT,
  211.     rescan,
  212.     {
  213.         {CCHR('G'),CCHR('G'),    metacG, (KEYMAP *)NULL},
  214.         {CCHR('V'),CCHR('V'),    metacV, (KEYMAP *)NULL},
  215.         {' ',    ' ',        metasp, (KEYMAP *)NULL},
  216.         {'%',    '%',        metapct,(KEYMAP *)NULL},
  217.         {'-',    '>',        metami, (KEYMAP *)NULL},
  218.         {'[',    'f',        metalb, (KEYMAP *)NULL},
  219.         {'l',    'x',        metal,    (KEYMAP *)NULL},
  220.         {'~',    CCHR('?'),    metatilde,(KEYMAP *)NULL},
  221.     }
  222. };
  223.  
  224. static    PF     fund_at[] = {
  225.     setmark,    /* ^@ */
  226.     gotobol,    /* ^A */
  227.     backchar,    /* ^B */
  228.     rescan,        /* ^C */
  229.     forwdel,    /* ^D */
  230.     gotoeol,    /* ^E */
  231.     forwchar,    /* ^F */
  232.     ctrlg,        /* ^G */
  233.     prefix,        /* ^H */
  234. };
  235.  
  236. static    PF     fund_CI[] = {
  237.         alignindent,    /* ^I */
  238.         };
  239.  
  240. /* ^I is selfinsert */
  241. static    PF     fund_CJ[] = {
  242.     indent,        /* ^J */
  243.     killline,    /* ^K */
  244.     reposition,    /* ^L */
  245.     newline,    /* ^M */
  246.     forwline,    /* ^N */
  247.     openline,    /* ^O */
  248.     backline,    /* ^P */
  249.     quote,        /* ^Q */
  250.     backisearch,    /* ^R */
  251.     forwisearch,    /* ^S */
  252.     twiddle,    /* ^T */
  253.     universal_argument,    /* ^U */
  254.     forwpage,    /* ^V */
  255.     killregion,    /* ^W */
  256.     prefix,        /* ^X */
  257.     yank,        /* ^Y */
  258.     spawncli,    /* ^Z */
  259. };
  260. static    PF     fund_esc[] = {
  261.     prefix,        /* esc */
  262.     rescan,        /* ^\ */  /* selfinsert is default on fundamental */
  263.     rescan,        /* ^] */
  264.     rescan,        /* ^^ */
  265.     rescan,        /* ^_ */
  266. };
  267. static    PF     fund_del[] = {
  268.     backdel,    /* DEL */
  269. };
  270.  
  271. static    PF     blink_rp[] = {
  272.     showmatch,    /* ) */
  273. };
  274. static    struct    KEYMAPE(3+IMAPEXT)    blinkmap = {
  275.     3,
  276.     3+IMAPEXT,
  277.     rescan,
  278.     {
  279.         {')',    ')',    blink_rp,    (KEYMAP *)NULL},
  280.         {'}',    '}',    blink_rp,    (KEYMAP *)NULL},
  281.         {']',    ']',    blink_rp,    (KEYMAP *)NULL},
  282.     }
  283. };
  284.  
  285. #ifndef    FUND_XMAPS
  286. #define NFUND_XMAPS    0    /* extra map sections after normal ones */
  287. #endif
  288.  
  289. static    struct    KEYMAPE(5+NFUND_XMAPS+IMAPEXT)    fundmap = {
  290.     5 + NFUND_XMAPS,
  291.     5 + NFUND_XMAPS + IMAPEXT,
  292.     selfinsert,
  293.     {
  294.         {CCHR('@'),CCHR('H'),    fund_at, (KEYMAP *)&helpmap},
  295.         {CCHR('I'),CCHR('I'),    fund_CI, (KEYMAP *)&cXmap},
  296.         {CCHR('J'),CCHR('Z'),    fund_CJ, (KEYMAP *)&cXmap},
  297.         {CCHR('['),CCHR('_'),    fund_esc,(KEYMAP *)&metamap},
  298.         {CCHR('?'),CCHR('?'),    fund_del,(KEYMAP *)NULL},
  299.     
  300. #ifdef    FUND_XMAPS
  301.         FUND_XMAPS,
  302. #endif
  303.     }
  304. };
  305.  
  306. static    PF     fill_sp[] = {
  307.     fillword,    /* ' ' */
  308. };
  309. static struct KEYMAPE(1+IMAPEXT)    fillmap = {
  310.     1,
  311.     1+IMAPEXT,
  312.     rescan,
  313.     {
  314.         {' ',    ' ',    fill_sp,    (KEYMAP *)NULL},
  315.     }
  316. };
  317.  
  318. static    PF     indent_lf[] = {
  319.     newline,    /* ^J */
  320.     rescan,        /* ^K */
  321.     rescan,        /* ^L */
  322.     indent,        /* ^M */
  323. };
  324. static    struct    KEYMAPE(1+IMAPEXT)    indntmap = {
  325.     1,
  326.     1+IMAPEXT,
  327.     rescan,
  328.     {
  329.         {CCHR('J'), CCHR('M'),    indent_lf,    (KEYMAP *)NULL},
  330.     }
  331. };
  332.  
  333. static    struct    KEYMAPE(1+IMAPEXT)    overwmap = {
  334.     0,
  335.     1+IMAPEXT,            /* 1 to avoid 0 sized array */
  336.     rescan,
  337.     {
  338.         /* unused dummy entry for VMS C */
  339.         {(KCHAR)0,    (KCHAR)0, (PF *)NULL,    (KEYMAP *)NULL},
  340.     }
  341. };
  342.  
  343. static    PF     dirednul[] = {
  344.     setmark,    /* ^@ */
  345.     gotobol,    /* ^A */
  346.     backchar,    /* ^B */
  347.     rescan,        /* ^C */
  348.     rescan,        /* ^D */
  349.     gotoeol,    /* ^E */
  350.     forwchar,    /* ^F */
  351.     ctrlg,        /* ^G */
  352.     prefix,        /* ^H */
  353. };
  354. static    PF     diredcl[] = {
  355.     reposition,    /* ^L */
  356.     forwline,    /* ^M */
  357.     forwline,    /* ^N */
  358.     rescan,        /* ^O */
  359.     backline,    /* ^P */
  360.     rescan,        /* ^Q */
  361.     backisearch,    /* ^R */
  362.     forwisearch,    /* ^S */
  363.     rescan,        /* ^T */
  364.     universal_argument, /* ^U */
  365.     forwpage,    /* ^V */
  366.     rescan,        /* ^W */
  367.     prefix,        /* ^X */
  368. };
  369. static    PF     diredcz[] = {
  370.     spawncli,    /* ^Z */
  371.     prefix,        /* esc */
  372.     rescan,        /* ^\ */
  373.     rescan,        /* ^] */
  374.     rescan,        /* ^^ */
  375.     rescan,        /* ^_ */
  376.     forwline,    /* SP */
  377. };
  378. static    PF     diredc[] = {
  379.     rescan,        /* c */
  380.     rescan,        /* d */
  381.     d_findfile,    /* e */
  382.     d_findfile,    /* f */
  383. };
  384. static    PF     diredn[] = {
  385.     forwline,    /* n */
  386.     rescan,         /* o */
  387.     backline,    /* p */
  388.     rescan,        /* q */
  389.     rescan,         /* r */
  390.     rescan,        /* s */
  391.     rescan,        /* t */
  392.     rescan,        /* u */
  393.     d_viewfile,    /* v */
  394.     rescan,        /* w */
  395.     rescan,        /* x */
  396. };
  397. static    PF     direddl[] = {
  398.     rescan,    /* del */
  399. };
  400.  
  401. #ifndef    DIRED_XMAPS
  402. #define    NDIRED_XMAPS    0    /* number of extra map sections */
  403. #endif
  404.  
  405. static    struct    KEYMAPE(6 + NDIRED_XMAPS + IMAPEXT)    diredmap = {
  406.     6 + NDIRED_XMAPS,
  407.     6 + NDIRED_XMAPS + IMAPEXT,
  408.     rescan,
  409.     {
  410.         {CCHR('@'),    CCHR('H'),    dirednul, (KEYMAP *)&helpmap},
  411.         {CCHR('L'),    CCHR('X'),    diredcl,  (KEYMAP *)&cXmap},
  412.         {CCHR('Z'),    ' ',        diredcz,  (KEYMAP *)&metamap},
  413.         {'c',        'f',        diredc,   (KEYMAP *)NULL},
  414.         {'n',        'x',        diredn,   (KEYMAP *)NULL},
  415.         {CCHR('?'),    CCHR('?'),    direddl,  (KEYMAP *)NULL},
  416. #ifdef    DIRED_XMAPS
  417.         DIRED_XMAPS,    /* map sections for dired mode keys    */
  418. #endif
  419.     }
  420. };
  421.  
  422. static    PF     bufflstk[] = {
  423.     zapbuffer,    /* k */
  424.     rescan,        /* l */
  425.     rescan,        /* m */
  426.     forwline,    /* n */
  427.     rescan,        /* o */
  428.     backline,    /* p */
  429.     rescan,        /* q */
  430.     rescan,        /* r */
  431.     savethisbuffer,    /* s */
  432.     rescan,        /* t */
  433.     seebuffer,    /* u */
  434. };
  435.  
  436. /* piggy-backing off dired mode, this is bufferlist mode (JAM)
  437. */
  438. #ifndef    BUFFERL_XMAPS
  439. #define    NBUFFERL_XMAPS    0    /* number of extra map sections */
  440. #endif
  441.  
  442. static    struct    KEYMAPE(5 + NBUFFERL_XMAPS + IMAPEXT)    bufflstmap = {
  443.     5 + NBUFFERL_XMAPS,
  444.     5 + NBUFFERL_XMAPS + IMAPEXT,
  445.     rescan,
  446.     {
  447.         {CCHR('@'),    CCHR('H'),    dirednul, (KEYMAP *)&helpmap},
  448.         {CCHR('L'),    CCHR('X'),    diredcl,  (KEYMAP *)&cXmap},
  449.         {CCHR('Z'),    ' ',        diredcz,  (KEYMAP *)&metamap},
  450.         {'k',        'u',        bufflstk, (KEYMAP *)NULL},
  451.         {CCHR('?'),    CCHR('?'),    direddl,  (KEYMAP *)NULL},
  452. #ifdef    BUFFERL_XMAPS
  453.         BUFFERL_XMAPS,    /* map sections for bufflst mode keys    */
  454. #endif
  455.     }
  456. };
  457.  
  458. /* give names to the maps, for use by help etc.
  459.  * If the map is to be bindable, it must also be listed in the
  460.  * function name table below with the same name.
  461.  * Maps created dynamicly currently don't get added here, thus are unnamed.
  462.  * Modes are just named keymaps with functions to add/subtract them from
  463.  * a buffer's list of modes.  If you change a mode name, change it in
  464.  * modes.c also.
  465.  */
  466.  
  467. /* IF YOU ADD / DELETE MODES, YOU MUST!! update MODES.C */
  468.  
  469. MAPS    map_table[] = {
  470.     /* fundamental map MUST be first entry */
  471.     {(KEYMAP *)&fundmap,    "main"},        /* 0 */
  472.     {(KEYMAP *)&fillmap,    "fill"},        /* 1 */
  473.     {(KEYMAP *)&indntmap,    "indent"},        /* 2 */
  474.     {(KEYMAP *)&blinkmap,    "C"},            /* 3 */
  475.     {(KEYMAP *)&overwmap,    "overwrite"},        /* 4 */
  476.     {(KEYMAP *)&metamap,    "esc prefix"},        /* 5 */
  477.     {(KEYMAP *)&cXmap,    "c-x prefix"},        /* 6 */
  478.     {(KEYMAP *)&cX4map,    "c-x 4 prefix"},    /* 7 */
  479.     {(KEYMAP *)&helpmap,    "help"},        /* 8 */
  480.     {(KEYMAP *)&diredmap,    "dired"},        /* 9 */
  481.     {(KEYMAP *)&bufflstmap,    "blist"},        /* 10 (JAM) */
  482. };
  483.  
  484. #define NMAPS    (sizeof map_table/sizeof(MAPS))
  485. int    nmaps = NMAPS;        /* for use by rebind in extend.c */
  486.  
  487. char *map_name(map)
  488. KEYMAP *map;
  489. {
  490.     MAPS *mp = &map_table[0];
  491.  
  492.     do {
  493.         if(mp->p_map == map) return mp->p_name;
  494.     } while(++mp < &map_table[NMAPS]);
  495.     return (char *)NULL;
  496. }
  497.  
  498. MAPS *name_mode(name)
  499. char *name;
  500. {
  501.     MAPS *mp = &map_table[0];
  502.  
  503.     do {
  504.         if(strcmp(mp->p_name,name)==0) return mp;
  505.     } while(++mp < &map_table[NMAPS]);
  506.     return (MAPS *)NULL;
  507. }
  508.  
  509. KEYMAP *name_map(name)
  510. char *name;
  511. {
  512.   MAPS *mp;
  513.   
  514.   return ((mp=name_mode(name))==NULL ? (KEYMAP *)NULL : mp->p_map);
  515. }
  516.  
  517. /* Warning: functnames MUST be in alphabetical order!  (due to binary
  518.  * search in name_function.)  If the function is prefix, it must be listed
  519.  * with the same name in the map_table above.
  520.  */
  521. static FUNCTNAMES CONSTANT functnames[] = {
  522.  
  523.  /* NOTE - All functions which begin with "%-" are invisible to
  524.   * the user. They are used because it was easier than defining
  525.   * tons of 'exception' keycodes because during debugging I could
  526.   * 'hand test' the function. Absolute correctness would suggest that
  527.   * the whole concept of silent_extend (see extend.c) be dumped, and
  528.   * K_* codes be defined for all kinds of functions like these here
  529.   * and the forcing of command names as is done in *key.c for hard
  530.   * key mapping. In any case, the help layer won't print them out 
  531.   * when doing a function dump and adding a new function to this table
  532.   * is exceptionally trivial exactly because silent_extend does exist (A
  533.   * big benefit right off is only this file needs recompiling vs all the
  534.   * files which use the keycode mapping tables).  (JAM)
  535.   */
  536.         {crashcheck,    "%-crash-check"},
  537.     {d_findfile,    "%-dired-find-file"},    /* moved and made */
  538.     {d_viewfile,    "%-dired-view"},    /* invisible (JAM) */
  539. #if 0 /* these were debug for something else.. */
  540.     {dosdir,    "%-dosdir"}, 
  541.     {dosget,    "%-dos-get-file-attr"}, 
  542.     {dosset,    "%-dos-set-file-attr"},
  543. #endif
  544.     {poptofilequiet,"%-efile"},    /* find-file w/prefilled fname */
  545.     {diredfiles_,    "%-files"},    /* supports EFFILE, file name compl */
  546. #ifdef WINDOWED
  547.         {mousecmd,      "%-mouse"},    /* raw mouse input */
  548. #endif
  549.     {shootmedead,    "%-shootme"},    /* emergency exit */
  550.         {donothing,     "%-zzzzz"},    /* empty event function */
  551.     {ManageAlarms, "alarms"},
  552.     {apropos_command, "apropos"},
  553.     {fillmode,    "auto-fill-mode"},
  554.     {indentmode,    "auto-indent-mode"},
  555.     {backchar,    "backward-char"},
  556.     {delbword,    "backward-kill-word"},
  557.     {gotobop,    "backward-paragraph"},
  558.     {backword,    "backward-word"},
  559.     {gotobob,    "beginning-of-buffer"},
  560.     {gotobol,    "beginning-of-line"},
  561.  
  562.     {showthematch,    "blink-match"},
  563.     {blinkparen,    "blink-matching-paren"},
  564.  
  565. #ifdef    BSMAP
  566.     {bsmap,        "bsmap-mode"},
  567. #endif
  568.  
  569.     {CindentOff,     "c-indent-off"},
  570.     {CindentOn,     "c-indent-on"},
  571.     {prefix,    "c-x 4 prefix"},
  572.     {prefix,    "c-x prefix"},
  573.     {executemacro,    "call-last-kbd-macro"},
  574.     {capword,    "capitalize-word"},
  575.     {blinkparen,    "cmode"},
  576.     {sysmake,    "compile"},    /* duplicate access */
  577.     {copyregion,    "copy-region-as-kill"},
  578. #ifdef REGEX
  579.     {cntmatchlines, "count-matches"},
  580.     {cntnonmatchlines,"count-non-matches"},
  581. #endif
  582.     {define_key,    "define-key"},
  583.     {backdel,    "delete-backward-char"},
  584.     {deblank,    "delete-blank-lines"},
  585.     {forwdel,    "delete-char"},
  586.     {delwhite,    "delete-horizontal-space"},
  587. #ifdef    REGEX
  588.     {delmatchlines, "delete-matching-lines"},
  589.     {delnonmatchlines,"delete-non-matching-lines"},
  590. #endif
  591.     {onlywind,    "delete-other-windows"},
  592.     {delwind,    "delete-window"},
  593.     {wallchart,    "describe-bindings"},
  594.     {desckey,    "describe-key-briefly"},
  595.     {digit_argument,"digit-argument"},
  596.     {dired,        "dired"},
  597.     {lowerregion,    "downcase-region"},
  598.     {lowerword,    "downcase-word"},
  599.     {showversion,    "emacs-version"},
  600.     {finishmacro,    "end-kbd-macro"},
  601.     {gotoeob,    "end-of-buffer"},
  602.     {gotoeol,    "end-of-line"},
  603.     {enlargewind,    "enlarge-window"},
  604.     {prefix,    "esc prefix"},
  605.     {evalexpr,    "eval-expression"},
  606.     {swapmark,    "exchange-point-and-mark"},
  607.     {extend,    "execute-extended-command"},
  608.     {fillpara,    "fill-paragraph"},
  609.     {filevisit,    "find-file"},
  610.     {poptofile,    "find-file-other-window"},
  611.     {forwchar,    "forward-char"},
  612.     {gotoeop,    "forward-paragraph"},
  613.     {forwword,    "forward-word"},
  614.     {bindtokey,    "global-set-key"},
  615.     {unbindtokey,    "global-unset-key"},
  616.     {gotoline,    "goto-line"},
  617.     {gotomatch,    "goto-match"},   /* matching paren, etc */
  618.     {hardtab,    "hard-tab"},
  619.     {prefix,    "help"},
  620.     {help_help,    "help-help"},
  621.     {bufferinsert,    "insert-buffer"},
  622.     {insert,    "insert-chars"},
  623.     {fileinsert,    "insert-file"},
  624.     {fillword,    "insert-with-wrap"},
  625.     {backisearch,    "isearch-backward"},
  626.     {forwisearch,    "isearch-forward"},
  627.     {justone,    "just-one-space"},
  628.     {ctrlg,        "keyboard-quit"},
  629.     {killbuffer,    "kill-buffer"},
  630.     {killline,    "kill-line"},
  631.     {killpara,    "kill-paragraph"},
  632.     {killregion,    "kill-region"},
  633.     {delfword,    "kill-word"},
  634.     {listbuffers,    "list-buffers"},
  635.     {evalbuffer,    "load-buffer"},
  636.     {evalfile,    "load-file"},
  637.     {localbind,    "local-set-key"},
  638.     {localunbind,    "local-unset-key"},
  639. #ifdef WINDOWED
  640. # ifdef SomeUnix
  641.     {sysmail,    "mail"},
  642. # endif
  643.     {sysmake,    "make"},    /* duplicate access */
  644. #endif
  645.     {makebkfile,    "make-backup-files"},
  646.     {negative_argument, "negative-argument"},
  647.     {newline,    "newline"},
  648.     {indent,    "newline-and-indent"},
  649. #ifdef WINDOWED
  650.     {makeerror,    "next-error"},
  651. #endif
  652.     {forwline,    "next-line"},
  653.     {openline,    "open-line"},
  654.     {nextwind,    "other-window"},
  655.     {myoverwrite,    "overwrite-mode"},
  656.     {backline,    "previous-line"},
  657.     {prevwind,    "previous-window"},
  658. /*     {showcwdir,    "pwd"},          useful?? it's in the title bar 
  659.                                          and the current buffer info */
  660.     {queryrepl,    "query-replace"},
  661. #ifdef    REGEX
  662.     {re_queryrepl,    "query-replace-regexp"},
  663. #endif
  664.     {quote,        "quoted-insert"},
  665.  
  666. #ifdef REGEX
  667.     {re_searchagain,"re-search-again"},
  668.     {re_backsearch, "re-search-backward"},
  669.     {re_forwsearch, "re-search-forward"},
  670. #endif
  671.     {reposition,    "recenter"},
  672.     {myrefresh,    "redraw-display"},
  673.     {filerevisit,    "reread-file"},
  674.     {reverto,    "revert-to-incremental"},
  675.     {filesave,    "save-buffer"},
  676.     {quit,        "save-buffers-kill-emacs"},
  677.     {savebuffers,    "save-some-buffers"},
  678.     {backpage,    "scroll-down"},
  679. #ifdef    GOSMACS
  680.     {back1page,    "scroll-one-line-down"},
  681.     {forw1page,    "scroll-one-line-up"},
  682. #endif
  683.     {pagenext,    "scroll-other-window"},
  684.     {forwpage,    "scroll-up"},
  685.     {searchagain,    "search-again"},
  686.     {backsearch,    "search-backward"},
  687.     {forwsearch,    "search-forward"},
  688.     {selfinsert,    "self-insert-command"},
  689. #ifdef WINDOWED
  690.     {NewWindowColor, "set-bg-color"},
  691. #endif
  692. #ifdef    REGEX
  693.     {setcasefold,    "set-case-fold-search"},
  694. #endif
  695.     {set_default_mode, "set-default-mode"},
  696. #ifdef WINDOWED
  697.     {NewTextColor,    "set-fg-color"},
  698.     {NewTouchedTextColor,    "set-fg2-color"},
  699. #endif
  700.     {setfillcol,    "set-fill-column"},
  701. #ifdef WINDOWED
  702.     {NewFont,    "set-font"},
  703. #endif
  704.     {setmark,    "set-mark-command"},
  705. #ifdef WINDOWED  /* duplicate color functions by other names */
  706.     {NewTextColor,    "set-text-color"},
  707.     {NewTouchedTextColor,    "set-touched-text-color"},
  708.     {NewWindowColor,    "set-window-color"},
  709.     {ttwindowsize,    "set-window-size"},
  710.     {spawncli2,    "shell-command"},
  711. # ifndef SomeUnix
  712.     {spawncli,    "shell-window"},
  713. # endif
  714. #else    /* WINDOWED */
  715. # ifdef CURSES
  716.     {spawncli2,    "shell-command"},
  717. # else
  718.     {spawncli,    "shell-command"},
  719. # endif
  720. #endif    /* WINDOWED */
  721.         {showbufferfile, "show-filename"},
  722.     {shrinkwind,    "shrink-window"},
  723.     {splitwind,    "split-window-vertically"},
  724.     {definemacro,    "start-kbd-macro"},
  725.     {usebuffer,    "switch-to-buffer"},
  726.     {poptobuffer,    "switch-to-buffer-other-window"},
  727.         {toggleverifytime, "toggle-check-file-timestamp"},
  728. #ifdef DOCRYPT
  729.     {toggleencrypt, "toggle-encrypt-state"},
  730. #endif
  731.     {togglejustnl,"toggle-just-write-newline"},
  732.     {togglemodified,"toggle-modified-state"},
  733.     {togglereadonly,"toggle-read-only"},
  734.     {toggleshowtouched,"toggle-show-touched-lines"},
  735. #ifdef MSW
  736.     {togglemenu,    "toggle-window-menu"},
  737. #endif
  738.  
  739.     {twiddle,    "transpose-chars"},
  740.         {doUndo,        "undo-last-undoable"},
  741.     {universal_argument, "universal-argument"},
  742. #ifdef SomeUnix
  743.         {peerprog,      "unix-exec"}, 
  744. # else
  745.         /* below, in ABC order {windowprog,    "win-exec"}, */
  746. # endif
  747.     {upperregion,    "upcase-region"},
  748.     {upperword,    "upcase-word"},
  749.     {fileview,    "view-file"},
  750.     {showcpos,    "what-cursor-position"},
  751.     {showline,    "what-line"},             /* GNU like */
  752. #ifdef MSW
  753.         {windowprog,    "win-exec"},
  754. #else
  755.         /* above, in ABC order {peerprog,      "unix-exec"}, */
  756. #endif
  757.     {filewrite,    "write-file"},
  758.     {yank,        "yank"},
  759. };
  760.  
  761. #define NFUNCT    (sizeof(functnames)/sizeof(FUNCTNAMES))
  762. int nfunct = NFUNCT;        /* used by help.c */
  763.  
  764. /* Package a FUNCTNAMES entry for help processing;
  765. * I like my data static. Call better be well behaved.
  766. */
  767. BOOL loadfunct(i, pfnp)
  768. int i;
  769. void *pfnp;
  770. {
  771.   FUNCTNAMES *fnp = (FUNCTNAMES *)pfnp;
  772.   bcopy(&functnames[i], fnp, sizeof(FUNCTNAMES));
  773.   return(TRUE);
  774. }
  775.  
  776. /*
  777.  * The general-purpose version of ROUND2 blows osk C (2.0) out of the water.
  778.  * (reboot required)  If you need to build a version of mg with less than 32
  779.  * or more than 511 functions, something better must be done.
  780.  * The version that should work, but doesn't is:
  781.  * #define ROUND2(x) (1+((x>>1)|(x>>2)|(x>>3)|(x>>4)|(x>>5)|(x>>6)|(x>>7)|\
  782.  *    (x>>8)|(x>>9)|(x>>10)|(x>>11)|(x>>12)|(x>>13)|(x>>14)|(x>>15)))
  783.  */
  784. #define ROUND2(x) (x<128?(x<64?32:64):(x<256?128:256))
  785.  
  786. static int name_fent(fname, flag)
  787. char *fname;
  788. int flag;
  789. {
  790.   register int    tryit;
  791.   register int    x = ROUND2(NFUNCT);
  792.   register int    base = 0;
  793.   register int    notit;
  794.  
  795.   do {
  796.     /* + can be used instead of | here if more efficent.    
  797.     */
  798.     if((tryit = base | x) < NFUNCT) {
  799.       if((notit = strcmp(fname, functnames[tryit].n_name)) >= 0) {
  800.          if(!notit) 
  801.             return (tryit);
  802.          base = tryit;
  803.          }
  804.       }
  805.     } while((x>>=1) || (tryit==1 && base==0));    /* try 0 once if needed */
  806.   return flag ? base : -1;
  807. }
  808.  
  809. /*
  810.  * Translate from function name to function pointer, using binary search.
  811.  */
  812. PF name_function(fname)
  813. char *fname;
  814. {
  815.   int i;
  816.  
  817.   if((i = name_fent(fname, FALSE)) >= 0) 
  818.     return (functnames[i].n_funct);
  819.   return (PF)NULL;
  820. }
  821.  
  822. /* complete function name 
  823. */
  824. int complete_function(fname, c)
  825. register char    *fname;
  826. int c;
  827. {
  828.   register int i, j, k, l;
  829.   int oj;
  830.  
  831.   i = name_fent(fname, TRUE);
  832.   for(j=0; (l=(int)fname[j]) && functnames[i].n_name[j]==(char)l; j++) 
  833.     {}
  834.   if(fname[j]!='\0') 
  835.     {
  836.     if(++i >= NFUNCT) 
  837.      return -2;    /* no match */
  838.     for(j=0; (l=(int)fname[j]) && functnames[i].n_name[j]==(char)l; j++) 
  839.      {}
  840.     if(fname[j]!='\0') 
  841.       return -2;    /* no match */
  842.     }
  843.   if(c==CCHR('M') && functnames[i].n_name[j]=='\0') 
  844.     return -1;
  845.   for(k=i+1; k<NFUNCT; k++) {        /* find last match */
  846.     for(l=0; functnames[k].n_name[l]==fname[l]; l++) {}
  847.     if(l<j) 
  848.     break;
  849.   }
  850.   k--;
  851.   oj = j;
  852.   if(k>i) {                    /* multiple matches */
  853.     while((l = functnames[i].n_name[j]) == functnames[k].n_name[j]) {
  854.       fname[j++] = (char)l;
  855.       if(l=='-' && c==' ') 
  856.          break;
  857.       }
  858.     if(j==oj) return -3;            /* ambiguous    */
  859.     } else {                    /* single match */
  860.         while(l = functnames[i].n_name[j]) {
  861.            fname[j++] = (char)l;
  862.            if(l=='-' && c==' ') 
  863.            break;
  864.     }
  865.     }
  866.   fname[j] = '\0';
  867.   return j - oj;
  868. }
  869.  
  870. /* translate from function pointer to function name. 
  871. */
  872. char *function_name(fpoint)
  873. register PF fpoint;
  874. {
  875.   register CONSTANT FUNCTNAMES    *fnp = &functnames[0];
  876.   
  877.   if(fpoint == prefix) 
  878.     return (char *)NULL;    /* ambiguous */
  879.   do {
  880.     if(fnp->n_funct == fpoint) 
  881.       return fnp->n_name;
  882.   } while(++fnp < &functnames[NFUNCT]);
  883.   return (char *)NULL;
  884. }
  885.